package org.xy.processor;

import java.io.IOException;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.xy.dao.BasicDAO;
import org.xy.dao.SchoolDAO;
import org.xy.dao.StudentDAO;
import org.xy.utils.CMDCaller;

@Component("templateTX")
public class TemplateTX {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	@Resource
	protected BasicDAO basicDAO;

	@Resource
	protected StudentDAO studentDAO;

	@Resource
	protected SchoolDAO schoolDAO;

	@Resource
	private TransactionTemplate txTemplate;

	public BasicDAO getBasicDAO() {
		return this.basicDAO;
	}

	public void setBasicDAO(BasicDAO basicDAO) {
		this.basicDAO = basicDAO;
	}

	public void setStudentDAO(StudentDAO studentDAO) {
		this.studentDAO = studentDAO;
	}

	public void setSchoolDAO(SchoolDAO schoolDAO) {
		this.schoolDAO = schoolDAO;
	}

	public void setTxTemplate(TransactionTemplate txTemplate) {
		this.txTemplate = txTemplate;
	}

	public static void startupDB() throws IOException {
		String command = "java -cp %HSQLDB_HOME%/hsqldb.jar org.hsqldb.Server -database.0 xydb -dbname.0 xydb";
		CMDCaller.callCMD(CMDCaller.PRE_NEW_AND_CLOSE_ORIGINAL_WINDOW, command);
	}

	public void shutdownDB() {
		this.basicDAO.executeSQL("SHUTDOWN;");
	}

	public void insertInSameTX(final boolean abortTx) {
		this.logger.info("School and student insert in the same transcation");

		this.txTemplate.execute(new TransactionCallbackWithoutResult() {

			@Override
			protected void doInTransactionWithoutResult(
					TransactionStatus txStatus) {
				schoolDAO.insertDefault();
				studentDAO.insertDefault();
				if (abortTx) {
					logger.info("Abort the school and student insert");
					throw new RuntimeException("Abort the transcation");
				}
			}
		});
	}

	public void insertInDiffTX(final boolean abortTx1, final boolean abortTx2) {
		this.logger.info("School and student insert in different transcation");
		this.txTemplate.execute(new TransactionCallbackWithoutResult() {

			@Override
			protected void doInTransactionWithoutResult(
					TransactionStatus txStatus) {
				schoolDAO.insertDefault();
				if (abortTx1) {
					logger.info("Abort the school insert");
					throw new RuntimeException(
							"Abort the transcation in school insert");
				}
			}

		});

		this.txTemplate.execute(new TransactionCallbackWithoutResult() {

			@Override
			protected void doInTransactionWithoutResult(
					TransactionStatus txStatus) {
				studentDAO.insertDefault();
				if (abortTx2) {
					logger.info("Abort the student insert");
					throw new RuntimeException(
							"Abort the transcation in student insert");
				}
			}

		});
	}

	public static void main(String[] args) throws IOException,
			InterruptedException {
		startupDB();
	}
}
